import networkx as nx
from typing import List, Dict, Tuple, Optional
import logging
from collections import defaultdict

class LogicAnalyzer:
    """逻辑分析模块"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def analyze_flowchart_structure(self, nodes: List[Dict], connections: List[Dict]) -> Dict:
        """分析流程图的逻辑结构"""
        self.logger.info("开始分析流程图逻辑结构")
        
        # 构建有向图
        graph = self._build_graph(nodes, connections)
        
        # 分析控制流结构
        structure = self._analyze_control_flow(graph, nodes)
        
        # 识别循环结构
        cycles = self._detect_cycles(graph)
        
        # 识别分支结构
        branches = self._analyze_branches(graph, nodes)
        
        # 构建完整的结构描述
        result = {
            'type': 'sequence',
            'nodes': [node['id'] for node in nodes],
            'connections': connections,
            'structure': structure,
            'cycles': cycles,
            'branches': branches,
            'graph_info': {
                'total_nodes': len(nodes),
                'total_connections': len(connections),
                'is_connected': nx.is_weakly_connected(graph),
                'has_cycles': len(cycles) > 0
            }
        }
        
        self.logger.info("逻辑结构分析完成")
        return result
    
    def _build_graph(self, nodes: List[Dict], connections: List[Dict]) -> nx.DiGraph:
        """构建有向图"""
        graph = nx.DiGraph()
        
        # 添加节点
        for node in nodes:
            graph.add_node(node['id'], **node)
        
        # 添加边
        for connection in connections:
            source = connection['source']
            target = connection['target']
            
            if source in graph and target in graph:
                graph.add_edge(source, target, **connection)
        
        return graph
    
    def _analyze_control_flow(self, graph: nx.DiGraph, nodes: List[Dict]) -> Dict:
        """分析控制流结构"""
        if not graph.nodes():
            return {'type': 'empty'}
        
        # 找到起始节点
        start_nodes = [node for node in graph.nodes() if graph.in_degree(node) == 0]
        end_nodes = [node for node in graph.nodes() if graph.out_degree(node) == 0]
        
        if not start_nodes:
            # 如果没有入度为0的节点，选择第一个节点作为起始
            start_nodes = [list(graph.nodes())[0]]
        
        if not end_nodes:
            # 如果没有出度为0的节点，选择最后一个节点作为结束
            end_nodes = [list(graph.nodes())[-1]]
        
        # 分析主要流程路径
        main_paths = self._find_main_paths(graph, start_nodes[0], end_nodes[0])
        
        # 分析决策节点
        decision_nodes = [node for node in nodes if node['type'] == 'decision']
        
        structure = {
            'type': 'sequence',
            'start_nodes': start_nodes,
            'end_nodes': end_nodes,
            'main_paths': main_paths,
            'decision_nodes': [node['id'] for node in decision_nodes],
            'subflows': []
        }
        
        # 分析子流程
        if decision_nodes:
            structure['subflows'] = self._analyze_subflows(graph, decision_nodes)
        
        return structure
    
    def _find_main_paths(self, graph: nx.DiGraph, start: str, end: str) -> List[List[str]]:
        """找到主要流程路径"""
        try:
            # 使用简单路径算法
            paths = list(nx.all_simple_paths(graph, start, end))
            
            if not paths:
                # 如果找不到从start到end的路径，尝试找到最长的路径
                longest_path = self._find_longest_path(graph)
                return [longest_path] if longest_path else []
            
            # 按路径长度排序，返回前3条主要路径
            paths.sort(key=len, reverse=True)
            return paths[:3]
            
        except nx.NetworkXNoPath:
            return []
    
    def _find_longest_path(self, graph: nx.DiGraph) -> List[str]:
        """找到图中的最长路径"""
        if not graph.nodes():
            return []
        
        # 使用拓扑排序找到最长路径
        try:
            # 如果是DAG，使用动态规划找最长路径
            if nx.is_directed_acyclic_graph(graph):
                return self._longest_path_dag(graph)
            else:
                # 对于有环的图，使用启发式方法
                return self._longest_path_heuristic(graph)
        except:
            return list(graph.nodes())
    
    def _longest_path_dag(self, graph: nx.DiGraph) -> List[str]:
        """在有向无环图中找最长路径"""
        # 拓扑排序
        topo_order = list(nx.topological_sort(graph))
        
        # 动态规划找最长路径
        dp = {node: 0 for node in graph.nodes()}
        prev = {node: None for node in graph.nodes()}
        
        for node in topo_order:
            for pred in graph.predecessors(node):
                if dp[pred] + 1 > dp[node]:
                    dp[node] = dp[pred] + 1
                    prev[node] = pred
        
        # 找到最长路径的终点
        end_node = max(dp, key=dp.get)
        
        # 重建路径
        path = []
        current = end_node
        while current is not None:
            path.append(current)
            current = prev[current]
        
        return path[::-1]
    
    def _longest_path_heuristic(self, graph: nx.DiGraph) -> List[str]:
        """启发式方法找最长路径"""
        # 从入度最小的节点开始
        start_node = min(graph.nodes(), key=lambda x: graph.in_degree(x))
        
        path = [start_node]
        current = start_node
        
        # 贪心选择下一个节点
        for _ in range(len(graph.nodes())):
            successors = list(graph.successors(current))
            if not successors:
                break
            
            # 选择出度最大的后继节点
            next_node = max(successors, key=lambda x: graph.out_degree(x))
            if next_node in path:
                break
            
            path.append(next_node)
            current = next_node
        
        return path
    
    def _detect_cycles(self, graph: nx.DiGraph) -> List[List[str]]:
        """检测图中的循环"""
        try:
            cycles = list(nx.simple_cycles(graph))
            return cycles
        except:
            return []
    
    def _analyze_branches(self, graph: nx.DiGraph, nodes: List[Dict]) -> List[Dict]:
        """分析分支结构"""
        branches = []
        
        for node in nodes:
            if node['type'] == 'decision':
                # 分析决策节点的分支
                node_id = node['id']
                successors = list(graph.successors(node_id))
                
                if len(successors) >= 2:
                    branch_info = {
                        'decision_node': node_id,
                        'branches': []
                    }
                    
                    for succ in successors:
                        # 分析每个分支
                        branch_path = self._analyze_branch_path(graph, node_id, succ)
                        branch_info['branches'].append({
                            'target': succ,
                            'path': branch_path,
                            'type': self._determine_branch_type(node, succ)
                        })
                    
                    branches.append(branch_info)
        
        return branches
    
    def _analyze_branch_path(self, graph: nx.DiGraph, start: str, end: str) -> List[str]:
        """分析分支路径"""
        try:
            paths = list(nx.all_simple_paths(graph, start, end))
            if paths:
                return paths[0]  # 返回第一条路径
        except:
            pass
        
        return [start, end]
    
    def _determine_branch_type(self, decision_node: Dict, target_node: str) -> str:
        """确定分支类型"""
        # 基于节点文本内容判断分支类型
        decision_text = decision_node.get('text', '').lower()
        
        if any(keyword in decision_text for keyword in ['是', '真', '成功', 'yes', 'true']):
            return 'true_branch'
        elif any(keyword in decision_text for keyword in ['否', '假', '失败', 'no', 'false']):
            return 'false_branch'
        else:
            return 'default_branch'
    
    def _analyze_subflows(self, graph: nx.DiGraph, decision_nodes: List[Dict]) -> List[Dict]:
        """分析子流程"""
        subflows = []
        
        for decision_node in decision_nodes:
            node_id = decision_node['id']
            
            # 分析决策节点的子流程
            subflow = {
                'type': 'decision',
                'condition_node': node_id,
                'true_branch': None,
                'false_branch': None
            }
            
            successors = list(graph.successors(node_id))
            
            if len(successors) >= 2:
                # 分析两个分支
                branch1 = self._analyze_branch_subflow(graph, successors[0])
                branch2 = self._analyze_branch_subflow(graph, successors[1])
                
                # 根据分支类型分配
                if self._is_true_branch(decision_node, successors[0]):
                    subflow['true_branch'] = branch1
                    subflow['false_branch'] = branch2
                else:
                    subflow['true_branch'] = branch2
                    subflow['false_branch'] = branch1
            
            subflows.append(subflow)
        
        return subflows
    
    def _analyze_branch_subflow(self, graph: nx.DiGraph, start_node: str) -> Dict:
        """分析分支子流程"""
        # 找到从start_node开始的最长路径
        path = self._find_path_from_node(graph, start_node)
        
        return {
            'type': 'sequence',
            'nodes': path
        }
    
    def _find_path_from_node(self, graph: nx.DiGraph, start: str) -> List[str]:
        """从指定节点开始找路径"""
        path = [start]
        current = start
        
        for _ in range(len(graph.nodes())):
            successors = list(graph.successors(current))
            if not successors:
                break
            
            # 选择第一个后继节点
            next_node = successors[0]
            if next_node in path:
                break
            
            path.append(next_node)
            current = next_node
        
        return path
    
    def _is_true_branch(self, decision_node: Dict, target_node: str) -> bool:
        """判断是否为真分支"""
        # 简化的判断逻辑
        decision_text = decision_node.get('text', '').lower()
        return any(keyword in decision_text for keyword in ['是', '真', '成功', 'yes', 'true'])
    
    def generate_flow_summary(self, analysis_result: Dict) -> Dict:
        """生成流程摘要"""
        summary = {
            'total_nodes': analysis_result['graph_info']['total_nodes'],
            'total_connections': analysis_result['graph_info']['total_connections'],
            'has_cycles': analysis_result['graph_info']['has_cycles'],
            'decision_count': len(analysis_result['structure']['decision_nodes']),
            'main_flow_length': len(analysis_result['structure']['main_paths'][0]) if analysis_result['structure']['main_paths'] else 0,
            'complexity': self._calculate_complexity(analysis_result)
        }
        
        return summary
    
    def _calculate_complexity(self, analysis_result: Dict) -> str:
        """计算流程复杂度"""
        total_nodes = analysis_result['graph_info']['total_nodes']
        decision_count = len(analysis_result['structure']['decision_nodes'])
        has_cycles = analysis_result['graph_info']['has_cycles']
        
        if total_nodes <= 5 and decision_count <= 1 and not has_cycles:
            return 'simple'
        elif total_nodes <= 15 and decision_count <= 3:
            return 'medium'
        else:
            return 'complex' 